




const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

const resolvePromise = (promise2, x, resolve, reject) => {
    if (x === promise2) {
        reject(new TypeError('重复调用promise2'))
    }
    if ((typeof x === 'object' && x !== null) || (typeof x === 'function')) {
        let called = false;
        try {
            let then = x.then
            if (typeof then === 'function') {
                then.call(x, (y) => {
                    if (called) return
                    called = true
                    resolvePromise(promise2, y, resolve, reject)
                }, (r) => {
                    if (called) return
                    called = true
                    reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (error) {
            if (called) return
            called = true
            reject(error)
        }
    } else {
        resolve(x)
    }

}

class MyPromise {
    constructor(executor) {
        this.status = PENDING // 记录状态
        this.value = undefined; // 成功返回值
        this.reason = undefined; // 失败错误信息
        this.onResolveCallback = []
        this.onRejectCallback = []

        const resolve = (value) => {  // 成功回调
            if (value instanceof Promise) {
                return value.then(resolve, reject)
            }
            if (this.status === PENDING) {
                this.status = FULFILLED
                this.value = value
                this.onResolveCallback.forEach(cb => cb(this.value))
            }

        }
        const reject = (reason) => {  // 失败回调
            if (this.status === PENDING) {
                this.status = REJECTED
                this.reason = reason
                this.onRejectCallback.forEach(cb => cb(this.reason))
            }

        }

        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }

    }
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
        onRejected = typeof onRejected === 'function' ? onRejected : v => { throw v }
        let promise2 = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) { // 成功
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        //处理 then的返回值 满足链式调用必须使用return Promise
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            if (this.status === REJECTED) {  //失败
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            if (this.status === PENDING) {
                this.onResolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                })
                this.onRejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.reason)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                })
            }


        })

        return promise2

    }

}


new MyPromise((resolve, reject) => {

    setTimeout((() => {
        debugger
        resolve(2)
    }), 100)
}).then(res => {
    console.log('成功', res)
}, (err) => {
    console.log('失败', err)
})


/***
 * 为什么要在promise2中使用异步？
 *    因为要在promise2执行过程中使用promise2
 * 
 * 
 */